#include <boost/bind.hpp>

#include "button.hpp"
#include "foreach.hpp"
#include "formatter.hpp"
#include "grid_widget.hpp"
#include "human_player.hpp"
#include "image_widget.hpp"
#include "info_panel_dialog.hpp"
#include "label.hpp"
#include "raster.hpp"
#include "scenario.hpp"
#include "tactics.hpp"
#include "texture.hpp"
#include "unit_utils.hpp"

namespace gui
{
using namespace graphics;

info_panel_dialog::info_panel_dialog(game::human_player& player)
  : dialog(0, screen_height() - 100, screen_width(), 100), player_(player)
{}

void info_panel_dialog::handle_draw() const
{
	const texture panel_background(texture::get("gui/opaque-background.png"));

	blit_texture(panel_background, x(), y(), width(), height(), 0.0, 0.0, 0.0,
	             width()/GLfloat(panel_background.width()),
	             height()/GLfloat(panel_background.height()));
				 
	const texture panel_top(texture::get("gui/opaque-border-top.png"));
	blit_texture(panel_top, x(), y(), width(), panel_top.height(), 0.0, 0.0, 0.0,
	             width()/GLfloat(panel_top.width()),
	             height()/GLfloat(panel_top.height()));

	dialog::handle_draw();
}

void info_panel_dialog::set_unit(game::unit_ptr u)
{
	unit_ = u;
	init();
}

void info_panel_dialog::set_unit2(game::unit_ptr u)
{
	unit2_ = u;
	init();
}

void info_panel_dialog::set_loc(const hex::location& loc)
{
	loc_ = loc;
	init();
}

void info_panel_dialog::init()
{
	clear();

	const SDL_Color color = graphics::color_white();
	if(unit_) {
		add_unit_info(*unit_, 0);
		add_tactics(unit_, 256);
	}

	if(unit2_) {
		add_unit_info(*unit2_, 512);
	}

	grid_ptr grid(new gui::grid(1));
	grid->add_col(label::create(formatter() << "Round " << game::scenario::current()->round(), color));
	if(loc_.valid()) {
		grid->add_col(label::create(formatter() << loc_, color));
	}
	add_widget(grid, 750, 0);
}

void info_panel_dialog::add_unit_info(const game::unit& unit, int xpos)
{
	const SDL_Color color = graphics::color_white();
	add_widget(widget_ptr(new image_widget(get_unit_image(unit))), xpos, 0);
	add_widget(label::create(unit.description(), color), xpos + 10, 54);

	const game::commander_unit* commander = &unit.get_commander();
	if(commander == &unit) {
		commander = NULL;
	}

	grid_ptr grid(new gui::grid(3));
	grid->set_hpad(10);

	grid->add_col(label::create("Health", color))
	     .add_col(label::create(formatter() << unit.hitpoints(), color))
		 .add_col();
	grid->add_col(label::create("Attack", color))
	     .add_col(label::create(formatter() << unit.attack(), color));
	if(commander) {
		grid->add_col(label::create(formatter() << "+" << commander->attack_bonus(), color));
	} else {
		grid->add_col();
	}

	grid->add_col(label::create("Defense", color))
	     .add_col(label::create(formatter() << unit.defense(), color));
	if(commander) {
		grid->add_col(label::create(formatter() << "+" << commander->defense_bonus(), color));
	} else {
		grid->add_col();
	}

	grid->add_col(label::create("Movement", color))
	     .add_col(label::create(formatter() << unit.moves_left(), color))
	     .add_col(label::create(formatter() << "/" << unit.movement(), color));

	add_widget(grid, xpos + 80, 0, dialog::MOVE_RIGHT);
}

void info_panel_dialog::add_tactics(game::unit_ptr unit, int xpos)
{
	using namespace game;

	const SDL_Color color = graphics::color_white();

	std::vector<const_tactic_ptr> tactics;
	tactic::get_available_tactics(*unit, tactics);

	int ypos = 0;
	foreach(const_tactic_ptr t, tactics) {
		gui::button* b(new gui::button(label::create(t->description(), color), boost::bind(&info_panel_dialog::apply_tactic, this, t, unit)));
		b->set_tooltip(t->help_string());
		b->set_enabled_calculator(boost::bind(&tactic::can_use, t, unit));
		add_widget(widget_ptr(b), xpos, ypos);
		ypos += b->height();
	}
}

void info_panel_dialog::apply_tactic(game::const_tactic_ptr tactic,  game::unit_ptr unit)
{
	tactic->apply(unit);
	init();
	player_.recalculate_routes();
}

}
